/*
 *
 * Copyright (c) 2020 The Raptor Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef RAPTOR_LITE_IMPL_ENDPOINT_H_
#define RAPTOR_LITE_IMPL_ENDPOINT_H_

#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <string>

namespace raptor {
class Container;
class EndpointImpl;
class Slice;

class Endpoint final {
    friend class ContainerImpl;
    friend class MiniContainer;

public:
    Endpoint(std::shared_ptr<EndpointImpl> impl = nullptr);
    ~Endpoint();

    // If attached to the container, it returns
    // a valid value, otherwise it returns uint64_t(-1) .
    uint32_t ConnectionId();

    // DO NOT close fd externally
    uint64_t SocketFd();
    uint16_t GetListenPort();

    std::string PeerString();
    std::string LocalString();

    // Bind the endpoint to the container. It means that the data
    // receiving and sending work is handed over to the container
    // to complete.
    // Same effect as call Container->AttachEndpoint(endpoint).
    void BindContainer(Container *container);

    // Must call BindContainer or AttachEndpoint before calling SendMsg.
    bool SendMsg(const Slice &slice);
    bool SendMsg(const void *data, size_t len);

    // Used directly, not bind with the container
    int SyncRecv(void *data, size_t len);
    int SyncSend(const void *data, size_t len);

    void Close(bool notify = false);

    std::string LocalIp();
    uint16_t LocalPort();
    std::string RemoteIp();
    uint16_t RemotePort();

    bool IsValid();
    void SetPrivateContext(intptr_t ctx);
    intptr_t PrivateContext();

private:
    std::shared_ptr<EndpointImpl> impl_;
};
} // namespace raptor

#endif // RAPTOR_LITE_IMPL_ENDPOINT_H_
